﻿using System;
using Microsoft.Practices.EnterpriseLibrary.ExceptionHandling;
using Microsoft.Practices.EnterpriseLibrary.Logging;
using Microsoft.Practices.EnterpriseLibrary.Validation;
using Microsoft.Practices.ServiceLocation;
using Microsoft.Practices.Unity;
using Microsoft.VisualStudio.TestTools.UnitTesting;
using vm.Aspects.Facilities;

namespace vm.Aspects.Tests.Facilities
{
    /// <summary>
    /// Summary description for FacilityRegistrarTests
    /// </summary>
    [TestClass]
    [DeploymentItem(".\\EntLib.config")]
    public class FacilityRegistrarIntegrationConfigFileTests
    {
        public TestContext TestContext { get; set; }

        #region Additional test attributes
        //
        // You can use the following additional attributes as you write your tests:
        //
        // Use ClassInitialize to run code before running the first test in the class
        // [ClassInitialize()]
        // public static void MyClassInitialize(TestContext testContext) { }
        //
        // Use ClassCleanup to run code after all tests in a class have run
        // [ClassCleanup()]
        // public static void MyClassCleanup() { }
        //
        // Use TestInitialize to run code before running each test 
        // [TestInitialize()]
        // public void MyTestInitialize() { }
        //
        // Use TestCleanup to run code after each test has run
        // [TestCleanup()]
        // public void MyTestCleanup() { }
        //
        #endregion

        [TestMethod]
        public void AllIsRegisteredConfigFileTest()
        {
            DIContainer.Reset();

            // here we need the CSL first
            DIContainer.Initialize();

            Facility.Registrar.Reset();

            lock (DIContainer.Root)
            {
                var registrations = DIContainer.Root.GetRegistrationsSnapshot();

                DIContainer.Root
                           .UnsafeRegister(Facility.Registrar, registrations)
                           ;
            }

            Assert.IsTrue(DIContainer.Root.IsRegistered<IExceptionPolicyProvider>(ExceptionPolicyProvider.RegistrationName));
            Assert.IsTrue(DIContainer.Root.IsRegistered<LoggingConfiguration>());
            Assert.IsFalse(DIContainer.Root.IsRegistered<LoggingConfiguration>(LogConfigProvider.TestLogConfigurationResolveName));

            Assert.IsTrue(DIContainer.Root.IsRegistered<IClock>());
            Assert.IsTrue(DIContainer.Root.IsRegistered<IGuidGenerator>());
            Assert.IsTrue(DIContainer.Root.IsRegistered<ValidatorFactory>());
            Assert.IsTrue(DIContainer.Root.IsRegistered<Lazy<LogWriter>>());
            Assert.IsTrue(DIContainer.Root.IsRegistered<Lazy<ExceptionManager>>());

            var clock = DIContainer.Root.Resolve<IClock>();

            Assert.IsTrue(clock is Clock);
            Assert.AreEqual(clock, Facility.Clock);

            var guidGen = ServiceLocator.Current.GetInstance<IGuidGenerator>();

            Assert.IsTrue(guidGen is GuidGenerator);
            Assert.AreEqual(guidGen, Facility.GuidGenerator);

            var vFactory = DIContainer.Root.Resolve<ValidatorFactory>();

            Assert.IsTrue(vFactory is ValidatorFactory);
            Assert.AreEqual(vFactory, Facility.ValidatorFactory);

            Assert.IsNotNull(Facility.LogWriter);
            Assert.IsNotNull(Facility.ExceptionManager);

            DIContainer.Reset();
        }

        // This test needs 30 sec. Activate it and test it only if there are changes to the log facility:
#if false
        [TestMethod]
        public void ModifiedLogConfigFileTest()
        {
            // Arrange
            DIContainer.Reset();
            DIContainer.Initialize();
            Facility.Registrar.Reset();

            lock (DIContainer.Root)
            {
                var registrations = DIContainer.Root.GetRegistrationsSnapshot();

                DIContainer.Root
                           .UnsafeRegister(registrations, Facility.Registrar, false)
                           ;
            }

            Assert.IsTrue(DIContainer.Root.IsRegistered<IExceptionPolicyProvider>(ExceptionPolicyProvider.RegistrationName));
            Assert.IsTrue(DIContainer.Root.IsRegistered<LoggingConfiguration>());
            Assert.IsFalse(DIContainer.Root.IsRegistered<LoggingConfiguration>(LogConfigProvider.TestLogConfigurationResolveName));

            Assert.IsTrue(DIContainer.Root.IsRegistered<IClock>());
            Assert.IsTrue(DIContainer.Root.IsRegistered<IGuidGenerator>());
            Assert.IsTrue(DIContainer.Root.IsRegistered<ValidatorFactory>());
            Assert.IsTrue(DIContainer.Root.IsRegistered<Lazy<LogWriter>>());
            Assert.IsTrue(DIContainer.Root.IsRegistered<Lazy<ExceptionManager>>());

            var clock = DIContainer.Root.Resolve<IClock>();

            Assert.IsTrue(clock is Clock);
            Assert.AreEqual(clock, Facility.Clock);

            var guidGen = ServiceLocator.Current.GetInstance<IGuidGenerator>();

            Assert.IsTrue(guidGen is GuidGenerator);
            Assert.AreEqual(guidGen, Facility.GuidGenerator);

            var vFactory = DIContainer.Root.Resolve<ValidatorFactory>();

            Assert.IsTrue(vFactory is ValidatorFactory);
            Assert.AreEqual(vFactory, Facility.ValidatorFactory);

            Assert.IsNotNull(Facility.ExceptionManager);
            Assert.IsNotNull(Facility.LogWriter);

            Facility.LogWriter.LogInfo("Test message #1");

            // Act: add our in-memory test trace listener to the General category
            var logConfig = XDocument.Load(LogConfigProvider.LogConfigurationFileName);

            var listeners = logConfig.Descendants("listeners")
                                     .Where(e => e.Parent.Attribute("name").Value == "General")
                                     .FirstOrDefault();

            listeners.Add(new XElement("add", new XAttribute("name", "Test Trace Listener")));
            logConfig.Save(LogConfigProvider.LogConfigurationFileName);
            Thread.Sleep(30000);

            // log new message in the general category of log listeners
            Facility.LogWriter.LogInfo("Test message #2");

            // Assert:

            var trace = string.Join(" ", TestTraceListener.Messages);

            // the new message should be in the test in-memory log
            Assert.IsFalse(string.IsNullOrWhiteSpace(trace));
            Assert.IsTrue(trace.Contains("Message: Test message #2"));
        }

#endif
        [TestMethod]
        public void AllTestIsRegisteredConfigFileTest()
        {
            DIContainer.Reset();
            Facility.Registrar.Reset();

            lock (DIContainer.Initialize())
            {
                var registrations = DIContainer.Root.GetRegistrationsSnapshot();

                DIContainer.Root
                           .UnsafeRegister(Facility.Registrar, registrations, true)
                           ;
            }

            Assert.IsTrue(DIContainer.Root.IsRegistered<IExceptionPolicyProvider>(ExceptionPolicyProvider.RegistrationName));
            Assert.IsFalse(DIContainer.Root.IsRegistered<LoggingConfiguration>());
            Assert.IsTrue(DIContainer.Root.IsRegistered<LoggingConfiguration>(LogConfigProvider.TestLogConfigurationResolveName));

            Assert.IsTrue(DIContainer.Root.IsRegistered<IClock>());
            Assert.IsTrue(DIContainer.Root.IsRegistered<IGuidGenerator>());
            Assert.IsTrue(DIContainer.Root.IsRegistered<ValidatorFactory>());
            Assert.IsTrue(DIContainer.Root.IsRegistered<Lazy<LogWriter>>());
            Assert.IsTrue(DIContainer.Root.IsRegistered<Lazy<ExceptionManager>>());

            var clock = DIContainer.Root.Resolve<IClock>();

            Assert.IsTrue(clock is TestClock);
            Assert.AreEqual(clock, Facility.Clock);

            var guidGen = ServiceLocator.Current.GetInstance<IGuidGenerator>();

            Assert.IsTrue(guidGen is TestGuidGenerator);
            Assert.AreEqual(guidGen, Facility.GuidGenerator);

            var vFactory = DIContainer.Root.Resolve<ValidatorFactory>();

            Assert.IsTrue(vFactory is ValidatorFactory);
            Assert.AreEqual(vFactory, Facility.ValidatorFactory);

            Assert.IsNotNull(Facility.LogWriter);
            Assert.IsNotNull(Facility.ExceptionManager);

            Facility.LogWriter.TraceInfo("Testing");

            var trace = string.Join(" ", TestTraceListener.Messages);

            Assert.IsFalse(string.IsNullOrWhiteSpace(trace));
            Assert.IsTrue(trace.Contains("Message: Testing"));

            DIContainer.Reset();
        }
    }
}
